{{!

  Copyright (c) Facebook, Inc. and its affiliates.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

}}{{!

Generates a top-level file to be imported in the user's service code. It provides
wrappers for each of the service handlers that the user is then able to extend.

The generated file is pretty big, but the bulk of the generation is done inside
the services/Promises and services/Callbacks partials.

}}
{{> common/AutoGeneratedPy}}

cimport cython
from cpython.version cimport PY_VERSION_HEX
from libc.stdint cimport (
    int8_t as cint8_t,
    int16_t as cint16_t,
    int32_t as cint32_t,
    int64_t as cint64_t,
)
from libcpp.memory cimport shared_ptr, make_shared, unique_ptr, make_unique
from libcpp.string cimport string
from libcpp cimport bool as cbool
from cpython cimport bool as pbool
from libcpp.vector cimport vector
from libcpp.set cimport set as cset
from libcpp.map cimport map as cmap
from cython.operator cimport dereference as deref
from cpython.ref cimport PyObject
from thrift.py3.common import (
  InterfaceSpec as __InterfaceSpec,
  MethodSpec as __MethodSpec,
  ArgumentSpec as __ArgumentSpec,
)
from thrift.py3.exceptions cimport (
    cTApplicationException,
    ApplicationError as __ApplicationError,
    cTApplicationExceptionType__UNKNOWN)
from thrift.py3.server cimport ServiceInterface, RequestContext, Cpp2RequestContext
from thrift.py3.server import RequestContext, pass_context
from folly cimport (
  cFollyPromise,
  cFollyUnit,
  c_unit
)
from thrift.py3.types cimport move
from thrift.py3.types import NumberType as __NumberType

if PY_VERSION_HEX >= 0x030702F0:  # 3.7.2 Final
    from thrift.py3.server cimport THRIFT_REQUEST_CONTEXT as __THRIFT_REQUEST_CONTEXT

cimport folly.futures
from folly.executor cimport get_executor
cimport folly.iobuf as __iobuf
import folly.iobuf as __iobuf
from folly.iobuf cimport move as move_iobuf

{{#program:has_stream?}}
from thrift.py3.stream cimport cServerStream, cResponseAndServerStream
{{/program:has_stream?}}
cimport {{#program:py3Namespaces}}{{value}}.{{/program:py3Namespaces}}{{program:name}}.types as _{{#program:py3Namespaces}}{{value}}_{{/program:py3Namespaces}}{{program:name}}_types
import {{#program:py3Namespaces}}{{value}}.{{/program:py3Namespaces}}{{program:name}}.types as _{{#program:py3Namespaces}}{{value}}_{{/program:py3Namespaces}}{{program:name}}_types
{{#program:includeNamespaces}}
{{#hasServices?}}
cimport {{#includeNamespace}}{{value}}.{{/includeNamespace}}services as _{{#includeNamespace}}{{value}}_{{/includeNamespace}}services
import {{#includeNamespace}}{{value}}.{{/includeNamespace}}services as _{{#includeNamespace}}{{value}}_{{/includeNamespace}}services
{{/hasServices?}}
{{#hasTypes?}}
import {{#includeNamespace}}{{value}}.{{/includeNamespace}}types as _{{#includeNamespace}}{{value}}_{{/includeNamespace}}types
cimport {{#includeNamespace}}{{value}}.{{/includeNamespace}}types as _{{#includeNamespace}}{{value}}_{{/includeNamespace}}types
{{/hasTypes?}}
{{/program:includeNamespaces}}

import asyncio
import functools
import sys
import traceback
import types as _py_types

{{#program:services}}
from {{#program:py3Namespaces}}{{value}}.{{/program:py3Namespaces}}{{program:name}}.services_wrapper cimport c{{service:name}}Interface
{{/program:services}}

{{> services/Promises}}

{{#program:services}}
cdef object _{{service:name}}_annotations = _py_types.MappingProxyType({
{{#service:annotations}}
    {{> Annotation}}
    {{#last?}}

    {{/last?}}
{{/service:annotations}}
})


@cython.auto_pickle(False)
cdef class {{service:name}}Interface(
    {{#service:extends}}{{#service:externalProgram?}}
    _{{#service:py3Namespaces}}{{value}}_{{/service:py3Namespaces}}{{!
        }}{{service:programName}}_services.{{/service:externalProgram?}}{{service:name}}Interface
    {{/service:extends}}
    {{^service:extends?}}
    ServiceInterface
    {{/service:extends?}}
):
    annotations = _{{service:name}}_annotations

    def __cinit__(self):
        self._cpp_obj = c{{service:name}}Interface(
            <PyObject *> self,
            get_executor()
        )
{{#service:functions}}{{^function:returns_sink?}}

    @staticmethod
    def pass_context_{{function:name}}(fn):
        return pass_context(fn)

    async def {{function:name}}(
            self{{#function:args}},
            {{field:py_name}}{{/function:args}}):
        raise NotImplementedError("async def {{function:name}} is not implemented")
{{/function:returns_sink?}}{{/service:functions}}
{{#service:functions}}{{^function:returns_sink?}}

    @staticmethod
    def __get_reflection_for_{{function:name}}():
        return __MethodSpec(
            name="{{function:name}}",
            arguments=[
                {{#function:args}}
                __ArgumentSpec(
                    name="{{field:name}}",
                    type={{#field:type}}{{> types/PythonType}}{{/field:type}},
                    kind={{#field:type}}{{> types/ThriftNumberType}}{{/field:type}},
                    annotations=_py_types.MappingProxyType({
                        {{#field:annotations}}
                        {{> Annotation }}
                        {{#last?}}

                        {{/last?}}
                        {{/field:annotations}}
                    }),
                ),
                {{/function:args}}
            ],
            result={{#function:returnType}}{{!
                }}{{#type:void?}}None{{/type:void?}}{{!
                }}{{#type:streamresponse?}}{{> services/StreamResponseClassName}}{{/type:streamresponse?}}{{!
                }}{{^type:void?}}{{> types/PythonType}}{{/type:void?}}{{!
                }}{{/function:returnType}},
            result_kind={{#function:returnType}}{{> types/ThriftNumberType}}{{/function:returnType}},
            exceptions=[
                {{#function:exceptions}}
                {{#field:type}}{{> types/PythonType}}{{/field:type}},
                {{/function:exceptions}}
            ],
            annotations=_py_types.MappingProxyType({
                {{#function:annotations}}
                {{> Annotation }}
                {{#last?}}

                {{/last?}}
                {{/function:annotations}}
            }),
        )
{{/function:returns_sink?}}{{/service:functions}}

    {{> reflection/GetReflectionMethod}}


{{/program:services}}

{{> services/Callbacks}}
